'use strict';
const path = require('path');
const fs = require('fs');
const ejs = require('ejs');
const _ = require('lodash');

// const data = {
//   description: 'resource',
//   name: 'resource',
//   attributes: [
//     {
//       name: 'name',
//       filed: 'name',
//       params: {
//         maxLength: 50,
//         minLength: 5,
//         multiple: false,
//         required: true,
//         type: 'string',
//         unique: true,
//       },
//     },
//   ],
// };

function mkdirs(dirname, callback) {
  fs.exists(dirname, exists => {
    if (exists) {
      callback();
    } else {
      mkdirs(path.dirname(dirname), () => {
        fs.mkdir(dirname, callback);
      });
    }
  });
}

async function createcontroller({ templateDir, controllerDir, data }) {
  const { name, dir } = data;

  return new Promise((resolve, reject) => {
    fs.readFile(path.join(templateDir, 'controller.ejs'), 'utf8', (err, tpl) => {
      if (!err) {
        const reg = /<script\b[^>]*>([\s\S]*)<\/script>/ig;
        const str = reg.exec(tpl)[1];
        const rended = ejs.render(str, Object.assign({ _ }, data));
        const fulldir = path.join(controllerDir, dir);

        mkdirs(fulldir, err => {
          if (!err) {
            fs.writeFile(path.join(fulldir, `${name}.js`), rended, 'utf8', (err, data) => {
              err ? reject(err): resolve(data);
            });
          } else {
            reject(err);
          }
        });
        return;
      }
      reject(err);
    });
  });
}

async function createService({ templateDir, serviceDir, data }) {
  const { name, dir} = data;

  return new Promise((resolve, reject) => {
    fs.readFile(path.join(templateDir, 'service.ejs'), 'utf8', (err, tpl) => {
      if (!err) {
        const reg = /<script\b[^>]*>([\s\S]*)<\/script>/ig;
        const str = reg.exec(tpl)[1];
        const rended = ejs.render(str, Object.assign({ _ }, data));
        const fulldir = path.join(serviceDir, dir);

        mkdirs(fulldir, err => {
          if (!err) {
            fs.writeFile(path.join(fulldir, `${name}.js`), rended, 'utf8', (err, data) => {
              err ? reject(err): resolve(data);
            });
          } else {
            reject(err);
          }
        });
      } else {
        reject(err);
      }
    });
  });
}

async function updateRouter({routerDir, data}) {
  const { name, dir} = data;
  return new Promise((resolve, reject) => {
    fs.readFile(path.join(routerDir, 'list.json'), 'utf8', (err, json) => {
      if (!err) {
        const { list } = JSON.parse(json);
        const item = dir.replace(/\//g, '.') + '.' + name;
        
        if (!list.includes(item)) {
          list.push(item);
          const rended = JSON.stringify({ list });

          fs.writeFile(path.join(routerDir, 'list.json'), rended, 'utf8', (err, data) => {
            err ? reject(err) : resolve(data);
          });
        } else {
          resolve({});
        }

      } else {
        reject(err);
      }
    });
  });
}

module.exports = {
  async generator(parameter) {
    const { codeGenerator: { templateDir, controllerDir, serviceDir, routerDir } } = this.config;
    const { name, table, description, attributes } = parameter;
    const obj = path.parse(name.split('.').join('/'));
    const data = {
      name: obj.name,
      dir: obj.dir,
      table, 
      description, 
      attributes
    };

    try {

      await createcontroller({ templateDir, controllerDir, data });
      await createService({ templateDir, serviceDir, data });
      await updateRouter({routerDir, data});

    } catch (error) {
      console.log(error);
      return error.message;
    }
  },
};

